package com.marco.dao.common.query;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

import java.io.Serializable;
import java.util.Date;
import static com.marco.dao.common.PropertyCover.*;
/**
 * @Author zixiaojun
 * @Description
 * @Date 2021/3/3 3:48 下午
 */
public class Filter implements Serializable{

    private static final long serialVersionUID = -8712381359441065075L;

    /** 默认是否忽略大小写 */
    private static final boolean DEFAULT_IGNORE_CASE = false;

    /** 属性 */
    private String property;

    /** 运算符 */
    private Operator operator;

    /** 值 */
    private Object value;

    /** 是否忽略大小写 */
    private Boolean ignoreCase = DEFAULT_IGNORE_CASE;

    /**
     * 构造方法
     */
    public Filter() {
    }

    /**
     * 运算符
     */
    public enum Operator {

        /** 等于 */
        eq,

        /** 不等于 */
        ne,

        /** 大于 */
        gt,

        /** 小于 */
        lt,

        /** 大于等于 */
        ge,

        /** 小于等于 */
        le,

        /** 相似 */
        like,

        /** 不相似 */
        notLike,

        /** 包含 */
        in,

        notIn,

        /** 为Null */
        isNull,

        /** 不为Null */
        isNotNull,

        /** 之间 */
        between,

        /** 聚合grouby */
        groupBy,

        distinct,

        limit,

        eqFmtDate,

        /** OR */
        or


    }

    /**
     * 构造方法
     *
     * @param property
     *            属性
     * @param operator
     *            运算符
     * @param value
     *            值
     */
    private Filter(String property, Operator operator, Object value) {
        this(property,operator,value,false);
    }

    /**
     * 构造方法
     *
     * @param property
     *            属性
     * @param operator
     *            运算符
     * @param value
     *            值
     * @param ignoreCase
     *            忽略大小写
     */
    private Filter(String property, Operator operator, Object value, boolean ignoreCase) {
        this.property = property;
        this.operator = operator;
        this.value = value;
        this.ignoreCase = ignoreCase;
    }


    /**
     * 返回等于筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 等于筛选
     */
    public static <T> Filter eq(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.eq, value);
    }


    /**
     * 返回等于筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 等于筛选
     */
    public static Filter eq(String property, Object value) {
        return new Filter(property, Operator.eq, value);
    }

    /**
     * 返回等于筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @param ignoreCase
     *            忽略大小写
     * @return 等于筛选
     */
    public static Filter eq(String property, Object value, boolean ignoreCase) {
        return new Filter(property, Operator.eq, value, ignoreCase);
    }

    /**
     * 返回不等于筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 不等于筛选
     */
    public static <T> Filter ne(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.ne, value);
    }

    /**
     * 返回不等于筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 不等于筛选
     */
    public static Filter ne(String property, Object value) {
        return new Filter(property, Operator.ne, value);
    }

    /**
     * 返回不等于筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @param ignoreCase
     *            忽略大小写
     * @return 不等于筛选
     */
    public static Filter ne(String property, Object value, boolean ignoreCase) {
        return new Filter(property, Operator.ne, value, ignoreCase);
    }

    /**
     * 返回大于筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 大于筛选
     */
    public static <T> Filter gt(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.gt, value);
    }

    /**
     * 返回大于筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 大于筛选
     */
    public static Filter gt(String property, Object value) {
        return new Filter(property, Operator.gt, value);
    }

    /**
     * 返回小于筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 小于筛选
     */
    public static <T> Filter lt(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.lt, value);
    }

    /**
     * 返回小于筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 小于筛选
     */
    public static Filter lt(String property, Object value) {
        return new Filter(property, Operator.lt, value);
    }

    /**
     * 返回大于等于筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 大于等于筛选
     */
    public static <T> Filter ge(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.ge, value);
    }

    /**
     * 返回大于等于筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 大于等于筛选
     */
    public static Filter ge(String property, Object value) {
        return new Filter(property, Operator.ge, value);
    }

    /**
     * 返回小于等于筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 小于等于筛选
     */
    public static <T> Filter le(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.le, value);
    }

    /**
     * 返回小于等于筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 小于等于筛选
     */
    public static Filter le(String property, Object value) {
        return new Filter(property, Operator.le, value);
    }

    /**
     * 返回相似筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 相似筛选
     */
    public static <T> Filter like(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.like, value);
    }

    /**
     * 返回相似筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 相似筛选
     */
    public static Filter like(String property, Object value) {
        return new Filter(property, Operator.like, value);
    }

    /**
     * 返回不相似筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 相似筛选
     */
    public static <T> Filter notLike(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.notLike, value);
    }

    /**
     * 返回不相似筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 相似筛选
     */
    public static Filter notLike(String property, Object value) {
        return new Filter(property, Operator.notLike, value);
    }


    /**
     * 返回包含筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 包含筛选
     */
    public static <T> Filter in(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.in, value);
    }

    /**
     * 返回包含筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 包含筛选
     */
    public static Filter in(String property, Object value) {
        return new Filter(property, Operator.in, value);
    }

    /**
     * 返回不包含筛选
     *
     * @param property
     *            属性lambda
     * @param value
     *            值
     * @return 不包含筛选
     */
    public static <T> Filter notIn(SFunction<T,?> property, Object value) {
        return new Filter(covertProperty(property), Operator.notIn, value);
    }

    /**
     * 返回不包含筛选
     *
     * @param property
     *            属性
     * @param value
     *            值
     * @return 不包含筛选
     */
    public static Filter notIn(String property, Object value) {
        return new Filter(property, Operator.notIn, value);
    }

    /**
     * 返回为Null筛选
     *
     * @param property
     *            属性lambda
     * @return 为Null筛选
     */
    public static <T> Filter isNull(SFunction<T,?> property) {
        return new Filter(covertProperty(property), Operator.isNull, null);
    }

    /**
     * 返回为Null筛选
     *
     * @param property
     *            属性
     * @return 为Null筛选
     */
    public static Filter isNull(String property) {
        return new Filter(property, Operator.isNull, null);
    }

    /**
     * 返回不为Null筛选
     *
     * @param property 属性lambda
     * @return 不为Null筛选
     */
    public static <T> Filter isNotNull(SFunction<T,?> property) {
        return new Filter(covertProperty(property), Operator.isNotNull, null);
    }

    /**
     * 返回不为Null筛选
     *
     * @param property 属性
     * @return 不为Null筛选
     */
    public static Filter isNotNull(String property) {
        return new Filter(property, Operator.isNotNull, null);
    }

    public static <T> Filter between(SFunction<T,?> property, Object start,Object end) {
        return new Filter(covertProperty(property), Operator.between, new Object[]{start,end});
    }

    /**
     * 返回之间的筛选
     */
    public static Filter between(String property, Object start,Object end) {
        return new Filter(property, Operator.between, new Object[]{start,end});
    }

    public static <T> Filter eqFmtDate(SFunction<T,?> property, Date date, SQLDatePattern pattern) {
        return new Filter(covertProperty(property), Operator.eqFmtDate, new Object[]{date,pattern.getPattern()});
    }

    /**
     * 日期格式化字段
     * @return
     */
    public static Filter eqFmtDate(String property, Date date, SQLDatePattern pattern) {
        return new Filter(property, Operator.eqFmtDate, new Object[]{date,pattern.getPattern()});
    }

    public static <T> Filter eqFmtDate(SFunction<T,?> property, Date date) {
        return eqFmtDate(covertProperty(property),date,SQLDatePattern.YYYY_MM_DD);
    }

    /**
     * 日期格式化字段
     * @return
     */
    public static Filter eqFmtDate(String property, Date date) {
        return eqFmtDate(property,date,SQLDatePattern.YYYY_MM_DD);
    }

    /**
     * 返回不为Null筛选
     *
     * @param property
     *            属性lambda
     */
    public static <T> Filter groupBy(SFunction<T,?> property) {
        return new Filter(covertProperty(property), Operator.groupBy, null);
    }

    /**
     * 返回不为Null筛选
     *
     * @param property
     *            属性
     */
    public static Filter groupBy(String property) {
        return new Filter(property, Operator.groupBy, null);
    }

    /**
     * 查询结果去重
     *
     * @param property
     *            属性lambda
     */
    public static <T> Filter distinct(SFunction<T,?> property) {
        return new Filter(covertProperty(property), Operator.distinct, null);
    }

    /**
     * 查询结果去重
     *
     * @param property
     *            属性
     */
    public static Filter distinct(String property) {
        return new Filter(property, Operator.distinct, null);
    }



    /**
     * 返回限制条数
     * @param limit 记录数
     */
    public static Filter limit(int limit) {
        return new Filter(null, Operator.limit, limit);
    }

    /**
     * 返回限制条数
     * @param start 开始位置
     * @param limit 记录数
     */
    public static Filter limit(int start,int limit) {
        return new Filter(null, Operator.limit, new Integer[]{start,limit});
    }

    /**
     * 返回忽略大小写筛选
     *
     * @return 忽略大小写筛选
     */
    public Filter ignoreCase() {
        this.ignoreCase = true;
        return this;
    }

    /**
     * 获取属性
     *
     * @return 属性
     */
    public String getProperty() {
        return property;
    }

    /**
     * 设置属性
     *
     * @param property
     *            属性
     */
    public void setProperty(String property) {
        this.property = property;
    }

    /**
     * 获取运算符
     *
     * @return 运算符
     */
    public Operator getOperator() {
        return operator;
    }

    /**
     * 设置运算符
     *
     * @param operator
     *            运算符
     */
    public void setOperator(Operator operator) {
        this.operator = operator;
    }

    /**
     * 获取值
     *
     * @return 值
     */
    public Object getValue() {
        return value;
    }

    /**
     * 设置值
     *
     * @param value
     *            值
     */
    public void setValue(Object value) {
        this.value = value;
    }

    /**
     * 获取是否忽略大小写
     *
     * @return 是否忽略大小写
     */
    public Boolean getIgnoreCase() {
        return ignoreCase;
    }

    /**
     * 设置是否忽略大小写
     *
     * @param ignoreCase
     *            是否忽略大小写
     */
    public void setIgnoreCase(Boolean ignoreCase) {
        this.ignoreCase = ignoreCase;
    }

    /**
     * 重写equals方法
     *
     * @param obj
     *            对象
     * @return 是否相等
     */
    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        if (this == obj) {
            return true;
        }
        Filter other = (Filter) obj;
        return new EqualsBuilder().append(getProperty(), other.getProperty()).append(getOperator(), other.getOperator()).append(getValue(), other.getValue()).isEquals();
    }

    /**
     * 重写hashCode方法
     *
     * @return HashCode
     */
    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37).append(getProperty()).append(getOperator()).append(getValue()).toHashCode();
    }



}
